package com.boot.security.server.controller;

import com.boot.security.server.annotation.LogAnnotation;
import com.boot.security.server.dao.JobDao;
import com.boot.security.server.model.JobModel;
import com.boot.security.server.page.table.PageTableHandler;
import com.boot.security.server.page.table.PageTableHandler.CountHandler;
import com.boot.security.server.page.table.PageTableHandler.ListHandler;
import com.boot.security.server.page.table.PageTableRequest;
import com.boot.security.server.page.table.PageTableResponse;
import com.boot.security.server.service.JobService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.quartz.CronExpression;
import org.quartz.SchedulerException;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.*;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;

@Api(tags = "定时任务")
@RestController
@RequestMapping("/jobs")
public class JobController {

    @Autowired
    private JobService jobService;
    @Autowired
    private JobDao jobDao;

    @LogAnnotation
    @ApiOperation("添加定时任务")
    @PostMapping
    public void add (@RequestBody JobModel jobModel) {
        JobModel model = jobDao.getByName(jobModel.getJobName());
        if (model != null) {
            throw new IllegalArgumentException(jobModel.getJobName() + "已存在");
        }

        jobModel.setIsSysJob(false);
        jobService.saveJob(jobModel);
    }

    @LogAnnotation
    @ApiOperation("修改定时任务")
    @PutMapping
    public void update (@RequestBody JobModel jobModel) {
        jobModel.setStatus(1);
        jobService.saveJob(jobModel);
    }

    @LogAnnotation
    @ApiOperation("删除定时任务")
    @DeleteMapping("/{id}")
    public void delete (@PathVariable Long id) throws SchedulerException {
        jobService.deleteJob(id);
    }

    @ApiOperation("根据id获取定时任务")
    @GetMapping("/{id}")
    public JobModel getById (@PathVariable Long id) {
        return jobDao.getById(id);
    }

    @GetMapping
    @ApiOperation(value = "定时任务列表")
    public PageTableResponse list (PageTableRequest request) {
        return new PageTableHandler(new CountHandler() {

            @Override
            public int count (PageTableRequest request) {
                return jobDao.count(request.getParams());
            }
        }, new ListHandler() {

            @Override
            public List<JobModel> list (PageTableRequest request) {
                List<JobModel> list = jobDao.list(request.getParams(), request.getOffset(), request.getLimit());
                return list;
            }
        }).handle(request);
    }

    @ApiOperation(value = "校验cron表达式")
    @GetMapping(params = "cron")
    public boolean checkCron (String cron) {
        return CronExpression.isValidExpression(cron);
    }

    @Autowired
    private ApplicationContext applicationContext;

    @ApiOperation(value = "springBean名字")
    @GetMapping("/beans")
    public List<String> listAllBeanName () {
        String[] strings = applicationContext.getBeanDefinitionNames();
        List<String> list = new ArrayList<>();
        for (String str : strings) {
            if (str.contains(".")) {
                continue;
            }
            Class<?> clazz = getClass(str);
            // 2018.07.26修改 上面注释的add添加了太多不认识的bean，改为下面的判断我们只添加service，bean少了不少
            if (clazz.isAnnotationPresent(Service.class) && str.toLowerCase().contains("service")) {
                list.add(str);
            }
        }
        // 2018.07.26修改排序
        Collections.sort(list);

        return list;
    }

    @ApiOperation(value = "springBean的无参方法")
    @GetMapping("/beans/{name}")
    public Set<String> listMethodName (@PathVariable String name) {
        Class<?> clazz = getClass(name);
        Method[] methods = clazz.getDeclaredMethods();

        Set<String> names = new HashSet<>();
        Arrays.asList(methods).forEach(m -> {
            int b = m.getModifiers();
            if (Modifier.isPublic(b)) {
                // 2018.07.26修改public方法的判断
                Class<?>[] classes = m.getParameterTypes();
                if (classes.length == 0) {
                    names.add(m.getName());
                }
            }
        });

        return names;
    }

    private Class<?> getClass (String name) {
        Object object = applicationContext.getBean(name);
        Class<?> clazz = object.getClass();
        if (AopUtils.isAopProxy(object)) {
            clazz = clazz.getSuperclass();
        }

        return clazz;
    }
}
